//
//  DBParserRuleChoice.m
//  parser
//
//  Created by Daniel Braun on 26/05/07.
//  Copyright 2007 __MyCompanyName__. All rights reserved.
//

#import "DBParserRuleChoice.h"
#import "DBParser.h"


@implementation DBParserRuleChoice

- (void) dealloc {
	[choices release];
	[super dealloc];
}

- (id) initWithAction:(SEL)act
{
	self=[super initWithAction:act];
	if (self) {
		choices=[[NSMutableArray arrayWithCapacity:10]retain];
	}
	return self;
}



- (DBParserRule *) appendChoice: (DBParserRule*) r
{
	[choices addObject:[r instantiateRule]];
	return self;
}

+ (id) choice: (DBParserRule*)r1, ...
{
	va_list ap;
	id rul=[[[[self class]alloc]initWithAction:(SEL)0]autorelease];
	if (!rul) return nil;
	[rul appendChoice:[r1 instantiateRule]];
	va_start(ap, r1);
	for (;;) {
		DBParserRule *r;
		r=va_arg(ap, DBParserRule *);
		if (!r) break;
		[rul appendChoice:[r instantiateRule]];
	}
	va_end(ap);
	return rul;
}

- (void) preProcess
{
	unsigned int i, count = [choices count];
	nla=0;
	int j,k;
	for (i = 0; i < count; i++) {
		DBParserRule * r = [choices objectAtIndex:i];
		[r preProcess];
	}
	for (i = 0; i < count-1; i++) {
		int *t1, *t2;
		DBParserRule * r1 = [choices objectAtIndex:i];
		t1=[r1 tokens];
		for (j=i+1;j<count; j++) {
			DBParserRule * r2 = [choices objectAtIndex:j];
			t2=[r2 tokens];
			for (k=0; k<_DBP_MAX_LA; k++) {
				if (t1[k]<0) break;
				if (t2[k]<0) break;
				if (t1[k]==t2[k]) {
					if (nla<k) nla=k;
				}
			}
		}
	}
}

- (void) invokeWithParser:(DBParser *)p
{
	unsigned int i, count = [choices count];
	int k;
	BOOL nm;
	[self beginWithParser:p];
	for (i = 0; i < count; i++) {
		DBParserRule * r = [choices objectAtIndex:i];
		int *t=[r tokens];
		nm=NO;
		for (k=0; k<=nla; k++) {
			if (t[k]!=[p _tlookAhead:k]) {
				nm=YES;
				break;
			}
			if (!nm) {
				[r invokeWithParser:p];
				[self matchedWithParser:p];
				return;
			}
		}
	}
	[p _nomatch:self];
}
- (NSString *) description
{
	return [NSString stringWithFormat:@"RULE choice"];
}

@end
